package org.example.message_queue.mqserver.core;

import org.example.message_queue.common.MqException;

public class Router {
    public boolean checkBindingKey(String bindingKey){
        if (bindingKey == null){
            return true;
        }
//        循环判断是否合法，排除存在非法字符的bindingKey
        for (int i = 0; i < bindingKey.length(); i++) {
            char ch = bindingKey.charAt(i);
//            大写
            if (ch >= 'A' && ch <='Z'){
                continue;
            }
//            小写
            if (ch >= 'a' && ch <= 'z'){
                continue;
            }
//            数字
            if (ch >= '0' && ch <= '9'){
                continue;
            }
//            特殊符号
            if (ch == '.' || ch == '_' || ch == '#' || ch == '*'){
                continue;
            }
            return false;
        }
//      用split方法将字符串切分
        String[] words = bindingKey.split("\\.");
//        循环判断切分后的部分，如果长度大于1且包含*或者#，如果包含了就是非法的
        for (String word : words){
            if (word.length()>1 && word.contains("*") || word.contains("#")){
                return false;
            }
        }
//        约定通配符之间的相邻关系
//      1. aaa.#.#.bbb    => 非法
//      2. aaa.#.*.bbb    => 非法
//      3. aaa.*.#.bbb    => 非法
//      4. aaa.*.*.bbb    => 合法
        for (int i = 0; i < words.length - 1; i++) {
            if (words[i].equals('#') && words[i+1].equals('#')){
                return false;
            }
            if (words[i].equals('#') && words[i+1].equals('*')){
                return false;
            }
            if (words[i].equals('*') && words[i+1].equals('#')){
                return false;
            }
        }
        return true;
    }

    public boolean checkRoutingKey(String routingKey){
        if (routingKey == null){
            return true;
        }
        for (int i = 0; i < routingKey.length(); i++) {
            char ch = routingKey.charAt(i);
            if (ch >='A' && ch <= 'Z'){
                continue;
            }
            if (ch >='a' && ch <= 'z'){
                continue;
            }
            if (ch >= '0' && ch <= '9') {
                continue;
            }
            if (ch == '.' || ch == '_') {
                continue;
            }
            return false;
        }
        return true;
    }

    public boolean route(ExchangeType exchangeType , Binding binding, Message message) throws MqException {
//      根据不同的type使用不同的判定转发规则
        if (exchangeType == ExchangeType.FANOUT){
            return true;
        }else if (exchangeType == ExchangeType.TOPIC){
            return routeTopic(binding,message);
        }else {
            throw new MqException("[Router] 交换机类型非法！ exchangeType="+exchangeType);
        }
    }

    private boolean routeTopic(Binding binding, Message message) {
        String[] routingTokens = message.getRoutingKey().split("//.");
        String[] bindingTokens = binding.getBindingKey().split("//.");

        int bindingIndex = 0;
        int routingIndex = 0;

        while(bindingIndex < bindingTokens.length &&routingIndex <routingTokens.length){
            if (bindingTokens[bindingIndex].equals("*")){
//                只能任意匹配一个
                routingIndex++;
                bindingIndex++;
            }else if (bindingTokens[bindingIndex].equals("#")){
//                #的情况，就是可以匹配0个或者多个字符串
                bindingIndex++;
                if (bindingTokens[bindingIndex] == null){
                    return true;
                }
                routingIndex = findNextMatch(routingTokens,routingIndex,bindingTokens[bindingIndex]);
                if (routingIndex == -1){
                    return false;
                }
                bindingIndex++;
                routingIndex++;
            }else {
//                普通字符串，相同即可
                if (!bindingTokens[bindingIndex].equals(routingTokens[routingIndex])){
                    return false;
                }
                bindingIndex++;
                routingIndex++;
            }
        }
//        最后还要判断，双方是否同时到达末尾
        if (routingIndex == routingTokens.length && bindingIndex == bindingTokens.length){
            return true;
        }
        return false;
    }

    private int findNextMatch(String[] routingTokens, int routingIndex, String bindingToken) {
        for (int i = routingIndex; i < routingTokens.length; i++) {
            if (routingTokens[i].equals(bindingToken)){
                return i;
            }
        }
        return -1;
    }

}
